#include "httphelper_v1.h"
#include <md5.h>
#include <curl/curl.h>
#include <logger.h>
#include <iostream>
#include <configure.h>
#include <cJSON.h>

namespace v20241120
{
    using namespace cores::common::configures;

    static HttpHelperV1 globalHttpHelper;

    HttpHelperV1::HttpHelperV1()
        : HttpHelper()
    {
    }

    HttpHelperV1::~HttpHelperV1()
    {
    }

    static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
    {
        ((std::string *)userp)->append((char *)contents, size * nmemb);
        return size * nmemb;
    }

    void HttpHelperV1::sendWarmRequest(const string &code)
    {
        string ket_str = code + Configure::toString("warming_token");
        string md5_key = md5(ket_str);
        string req_url = Configure::toString("warming_url") + "?msg=" + code + "&msgPwd=" + md5_key;
        XLOG("req_url : %s", req_url);

        curl_global_init(CURL_GLOBAL_DEFAULT);
        auto curl = curl_easy_init();

        if (curl)
        {
            std::string readBuffer;
            curl_easy_setopt(curl, CURLOPT_URL, req_url.c_str());
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);

            /* Perform the request, res will get the return code */
            auto res = curl_easy_perform(curl);

            /* Check for errors */
            if (res != CURLE_OK)
            {
                XERROR("curl_easy_perform() failed: %s", curl_easy_strerror(res));
            }

            /* Always cleanup */
            curl_easy_cleanup(curl);

            XLOG("curl ok!");
        }
        curl_global_cleanup();
    }

    string HttpHelperV1::getConfigFromApi(const string &stationCode)
    {
        string ket_str = stationCode + Configure::toString("warming_token");
        string md5_key = md5(ket_str);
        string req_url = Configure::toString("config_api_url") + "?stationCode=" + stationCode + "&str=" + md5_key + "&version=" + Configure::toString("service_version");
        std::string api_res;
        XLOG(req_url.c_str());

        XLOG("初始化CURL");
        curl_global_init(CURL_GLOBAL_DEFAULT);
        auto curl = curl_easy_init();

        if (curl)
        {   
            XLOG("成功初始化CURL");
            string readBuffer;
            curl_easy_setopt(curl, CURLOPT_URL, req_url.c_str());
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);

            /* Perform the request, res will get the return code */
            auto res = curl_easy_perform(curl);

            /* Check for errors */
            if (res != CURLE_OK)
            {
                // fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
                XERROR("调用方法curl_easy_perform()失败，失败原因:%s", curl_easy_strerror(res));
            }

            XLOG(readBuffer.c_str());

            /* Always cleanup */
            curl_easy_cleanup(curl);

            cJSON *json_root_ = cJSON_Parse(readBuffer.c_str());
            auto item = cJSON_GetObjectItem(json_root_, "content");

            if (item != NULL)
            {
                std::string item_str(cJSON_Print(item));
                api_res = item_str;
                // api_res = item->valuestring;
                // XLOG("成功获取信息: %s", api_res);
            }
            else
            {
                XERROR("未能获取信息");
            }

            if (!readBuffer.empty())
                readBuffer.clear();

            cJSON_Delete(json_root_);
        }
        curl_global_cleanup();

        return api_res;
    }

    bool HttpHelperV1::compareFileVersion()
    {
        string ket_str = Configure::toString("station_code") + Configure::toString("warming_token");
        string md5_key = md5(ket_str);
        string req_url = Configure::toString("version_api_url") + "?stationCode=" + Configure::toString("station_code") + "&msgPwd=" + md5_key;
        cout << "req_url:" << req_url << endl;

        bool api_res = false;

        curl_global_init(CURL_GLOBAL_DEFAULT);
        auto curl = curl_easy_init();

        if (curl)
        {
            string readBuffer;
            curl_easy_setopt(curl, CURLOPT_URL, req_url.c_str());
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);

            /* Perform the request, res will get the return code */
            auto res = curl_easy_perform(curl);

            bool is_succ = true;
            /* Check for errors */
            if (res != CURLE_OK)
            {
                is_succ = false;
                std::string error_msg(curl_easy_strerror(res));
                std::cout << "Get file version failed: " << error_msg << std::endl;
                XERROR("Get file version failed -> %s", error_msg.c_str());
            }

            /* Always cleanup */
            curl_easy_cleanup(curl);

            if (is_succ)
            {
                // 请求成功，则解析json，比对版本号
                cJSON *json_root_ = cJSON_Parse(readBuffer.c_str());
                auto item = cJSON_GetObjectItem(json_root_, "version");

                if (item != NULL)
                {
                    XLOG("get version info by api");

                    int exe_version_server = item->valueint;
                    if (exe_version_server != Configure::toInt("local_exe_version"))
                    {
                        api_res = true;

                        item = cJSON_GetObjectItem(json_root_, "file_name");
                        if (item != NULL)
                        {
                            Configure::setValue("exe_server_file_name", string(item->valuestring));
                        }
                    }
                }

                if (!readBuffer.empty())
                    readBuffer.clear();

                cJSON_Delete(json_root_);
            }
        }
        curl_global_cleanup();

        return api_res;
    }

    static size_t writeData(void *ptr, size_t size, size_t nmemb, FILE *stream)
    {
        try
        {
            /* code */
            size_t written = fwrite(ptr, size, nmemb, stream);
            return written;
        }
        catch (const std::exception &e)
        {
            XERROR(e.what());
            return 0;
        }
    }

    void HttpHelperV1::downloadFile()
    {
        curl_global_init(CURL_GLOBAL_DEFAULT);
        CURL *curl = curl_easy_init();
        if (curl)
        {
            auto download_url = Configure::toString("exe_download_url") + "/" + Configure::toString("exe_server_file_name");

            FILE *fp = fopen(Configure::toString("exe_file_name").c_str(), "wb");
            curl_easy_setopt(curl, CURLOPT_URL, download_url.c_str());
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeData);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
            CURLcode res = curl_easy_perform(curl);
            curl_easy_cleanup(curl);
            fclose(fp);

            if (res != CURLE_OK)
            {
                std::string error_msg(curl_easy_strerror(res));
                XERROR("Failed to download exe-> %s", error_msg.c_str());
            }
            else
            {
                XLOG("Download successfully -> %s", Configure::toString("exe_file_name"));
            }
        }

        curl_global_cleanup();
    }
}
